import ttkbootstrap as ttkb
from ttkbootstrap.constants import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.dates import DateFormatter, DayLocator, MonthLocator, date2num
from matplotlib.patches import FancyBboxPatch
from datetime import datetime, timedelta
import numpy as np
from utils.export_handler import export_figure_to_pdf
from tkinter import messagebox

# Windows 中文显示适配（关键：避免 matplotlib 中文乱码）
plt.rcParams.update({
    "font.family": ["Microsoft YaHei", "SimHei", "Arial"],  # Windows 系统字体
    "font.size": 10,
    "axes.facecolor": "#f8f9fa",
    "axes.grid": True,
    "grid.color": "#dee2e6",
    "grid.linewidth": 0.8,
    "xtick.direction": "in",
    "ytick.direction": "in",
    "figure.facecolor": "white",
    "figure.edgecolor": "none",
    "axes.unicode_minus": False  # 解决负号显示问题
})

class GanttPanel(ttkb.Frame):
    def __init__(self, parent):
        super().__init__(parent, padding=(10, 10))
        self.parent = parent  # 父容器（right_vertical_pane）
        self.tasks = []  # 任务数据（ID 为整数）
        self.zoom_level = 1.0  # 缩放级别（1.0=默认）
        self.show_grid = True  # 网格线显示状态
        self._build_ui()

    def _build_ui(self):
        """甘特图UI：标题+工具栏+绘图区（Windows 布局适配）"""
        # 1. 标题栏
        self.title_frame = ttkb.Frame(self)
        self.title_frame.pack(fill=X, anchor=N, pady=(0, 8))
        self.title_label = ttkb.Label(self.title_frame, text="项目甘特图")
        self.title_label.pack(side=LEFT)
        
        self.divider = ttkb.Separator(self, orient=HORIZONTAL)
        self.divider.pack(fill=X, pady=(0, 8))
        
        # 2. 工具栏（Windows 按钮风格）
        self.tool_frame = ttkb.Frame(self)
        self.tool_frame.pack(fill=X, anchor=N, pady=(0, 8))
        
        self.zoom_in_btn = ttkb.Button(
            self.tool_frame, text="放大", command=self.zoom_in,
            bootstyle=OUTLINE, width=8
        )
        self.zoom_in_btn.pack(side=LEFT, padx=(0, 8))
        
        self.zoom_out_btn = ttkb.Button(
            self.tool_frame, text="缩小", command=self.zoom_out,
            bootstyle=OUTLINE, width=8
        )
        self.zoom_out_btn.pack(side=LEFT, padx=(0, 8))
        
        self.grid_btn = ttkb.Button(
            self.tool_frame, text="隐藏网格", command=self.toggle_grid,
            bootstyle=OUTLINE, width=10
        )
        self.grid_btn.pack(side=LEFT, padx=(0, 8))
        
        self.export_btn = ttkb.Button(
            self.tool_frame, text="导出PDF", command=self.export_to_pdf,
            bootstyle=PRIMARY, width=10
        )
        self.export_btn.pack(side=LEFT, padx=(0, 8))
        
        # 3. 绘图区（matplotlib 嵌入 Windows 窗口）
        self.plot_frame = ttkb.Frame(self)
        self.plot_frame.pack(fill=BOTH, expand=YES)
        
        # 创建 Figure（Windows 分辨率适配：dpi=100）
        self.fig, self.ax = plt.subplots(figsize=(12, 6), dpi=100)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame)
        self.canvas.draw()
        
        # 嵌入到 Tkinter 窗口（Windows 父子窗口适配）
        self.canvas.get_tk_widget().pack(fill=BOTH, expand=YES)
        
        # 绑定交互事件（Windows 鼠标操作适配）
        self.canvas.mpl_connect("scroll_event", self._on_mouse_scroll)  # 滚轮缩放
        self.canvas.mpl_connect("button_press_event", self._on_mouse_press)  # 鼠标按下
        self.canvas.mpl_connect("button_release_event", self._on_mouse_release)  # 鼠标释放
        self.canvas.mpl_connect("motion_notify_event", self._on_mouse_drag)  # 鼠标拖拽
        
        # 拖拽状态变量
        self.is_dragging = False
        self.drag_start_x = 0

    def update_gantt(self, tasks):
        """更新甘特图数据（任务 ID 为整数）"""
        self.tasks = tasks
        self._draw_gantt()

    def _draw_gantt(self):
        """绘制甘特图（Windows 样式：圆角+阴影+中文）"""
        self.ax.clear()
        
        if not self.tasks:
            # 无任务提示（中文适配）
            self.ax.text(
                0.5, 0.5, "当前项目无任务数据\n请在左侧任务列表添加任务",
                ha="center", va="center", transform=self.ax.transAxes,
                fontsize=12, color="#6c757d", fontfamily="Microsoft YaHei"
            )
            self.canvas.draw()
            return
        
        # 1. 处理任务数据（ID 为整数，日期格式适配）
        task_names = []
        start_dates = []
        durations = []
        priorities = []
        statuses = []
        progresses = []
        
        for task in self.tasks:
            (task_id, name, priority, owner, start_str, end_str, 
             status, progress, desc, dependency) = task
            
            # 转换日期（处理 Windows 日期格式）
            try:
                start_date = datetime.strptime(start_str, "%Y-%m-%d")
                end_date = datetime.strptime(end_str, "%Y-%m-%d")
            except ValueError:
                messagebox.showwarning("日期错误", f"任务「{name}」日期格式错误（应为 YYYY-MM-DD）", parent=self)
                continue
            
            # 计算时长（天）
            duration = (end_date - start_date).days + 1  # 包含首尾日
            
            # 存储数据（任务名带负责人，Windows 显示适配）
            task_names.append(f"{name}（{owner if owner else '未指定'}）")
            start_dates.append(date2num(start_date))
            durations.append(duration)
            priorities.append(priority)
            statuses.append(status)
            progresses.append(progress)
        
        # 2. 设置 Y 轴（任务名称，中文显示）
        y_pos = np.arange(len(task_names))
        self.ax.set_yticks(y_pos)
        self.ax.set_yticklabels(task_names, fontsize=9, va="center", fontfamily="Microsoft YaHei")
        self.ax.set_ylim(-0.5, len(task_names) - 0.5)
        
        # 3. 设置 X 轴（日期，Windows 显示粒度适配）
        min_date = min(start_dates) - 2
        max_date = max([s + d for s, d in zip(start_dates, durations)]) + 2
        self.ax.set_xlim(min_date * self.zoom_level, max_date * self.zoom_level)
        
        # 日期格式（按缩放级别切换）
        if self.zoom_level > 1.5:
            self.ax.xaxis.set_major_locator(DayLocator(interval=1))
            self.ax.xaxis.set_major_formatter(DateFormatter("%m-%d", fontfamily="Microsoft YaHei"))
        elif self.zoom_level > 0.5:
            self.ax.xaxis.set_major_locator(DayLocator(interval=7))
            self.ax.xaxis.set_major_formatter(DateFormatter("%m-%d", fontfamily="Microsoft YaHei"))
        else:
            self.ax.xaxis.set_major_locator(MonthLocator())
            self.ax.xaxis.set_major_formatter(DateFormatter("%Y-%m", fontfamily="Microsoft YaHei"))
        
        # 旋转 X 轴标签（避免重叠）
        plt.setp(self.ax.xaxis.get_majorticklabels(), rotation=45, ha="right")
        
        # 4. 绘制甘特图条形（Windows 视觉风格：圆角+阴影）
        bar_height = 0.6
        priority_color_map = {"高": "#dc3545", "中": "#ffc107", "低": "#28a745"}
        
        for i, (start, duration, priority, status, progress) in enumerate(
            zip(start_dates, durations, priorities, statuses, progresses)
        ):
            # 基础条形颜色（状态适配）
            base_color = priority_color_map.get(priority, "#6c757d")
            if status == "已完成":
                base_color = "#6c757d"
            elif status == "延期":
                base_color = "#dc3545"
            
            # 圆角条形（Windows 美观适配）
            bbox = FancyBboxPatch(
                (start * self.zoom_level, i - bar_height/2),
                duration * self.zoom_level, bar_height,
                boxstyle="round,pad=0.02",
                facecolor=base_color,
                edgecolor="#343a40",
                linewidth=0.8,
                alpha=0.8
            )
            self.ax.add_patch(bbox)
            
            # 进度条（覆盖在基础条形上）
            progress_width = duration * (progress / 100)
            if progress_width > 0:
                progress_bbox = FancyBboxPatch(
                    (start * self.zoom_level, i - bar_height/2),
                    progress_width * self.zoom_level, bar_height,
                    boxstyle="round,pad=0.02",
                    facecolor="#007bff",
                    edgecolor="#0056b3",
                    linewidth=0.5,
                    alpha=0.9
                )
                self.ax.add_patch(progress_bbox)
                
                # 进度文本（白色加粗，Windows 显示适配）
                progress_text = f"{progress}%"
                self.ax.text(
                    start * self.zoom_level + (duration * self.zoom_level)/2,
                    i,
                    progress_text,
                    ha="center", va="center",
                    fontsize=8, color="white", fontweight="bold", fontfamily="Microsoft YaHei"
                )
        
        # 5. 网格和样式（Windows 主题适配）
        self.ax.grid(self.show_grid, axis="x", linestyle="-", alpha=0.7)
        self.ax.grid(False, axis="y")  # Y 轴不显示网格
        self.ax.set_axisbelow(True)
        
        # 隐藏顶部/右侧边框（现代 UI 风格）
        self.ax.spines["top"].set_visible(False)
        self.ax.spines["right"].set_visible(False)
        self.ax.spines["left"].set_color("#dee2e6")
        self.ax.spines["bottom"].set_color("#dee2e6")
        
        # 调整布局（避免标签截断）
        plt.tight_layout()
        self.canvas.draw()

    # ---------------------- 交互功能（Windows 鼠标适配） ----------------------
    def zoom_in(self):
        """放大：Windows 滚轮步长适配"""
        if self.zoom_level < 3.0:
            self.zoom_level += 0.2
            self._draw_gantt()

    def zoom_out(self):
        """缩小：Windows 滚轮步长适配"""
        if self.zoom_level > 0.2:
            self.zoom_level -= 0.2
            self._draw_gantt()

    def _on_mouse_scroll(self, event):
        """鼠标滚轮缩放（Windows 滚轮方向适配）"""
        if event.button == "up":
            self.zoom_in()
        elif event.button == "down":
            self.zoom_out()

    def _on_mouse_press(self, event):
        """鼠标按下：Windows 左键拖拽"""
        if event.button == 1:  # 左键
            self.is_dragging = True
            self.drag_start_x = event.xdata if event.xdata is not None else 0

    def _on_mouse_release(self, event):
        """鼠标释放：结束拖拽"""
        if event.button == 1:
            self.is_dragging = False

    def _on_mouse_drag(self, event):
        """鼠标拖拽：平移甘特图（Windows 像素适配）"""
        if not self.is_dragging or event.xdata is None:
            return
        
        delta_x = self.drag_start_x - event.xdata
        current_xlim = self.ax.get_xlim()
        new_xlim = (current_xlim[0] - delta_x, current_xlim[1] - delta_x)
        
        self.ax.set_xlim(new_xlim)
        self.drag_start_x = event.xdata
        self.canvas.draw()

    def toggle_grid(self):
        """切换网格线（Windows 显示状态适配）"""
        self.show_grid = not self.show_grid
        self.grid_btn.config(text="显示网格" if not self.show_grid else "隐藏网格")
        self._draw_gantt()

    def export_to_pdf(self):
        """导出 PDF（Windows 路径适配）"""
        if not self.tasks:
            messagebox.showwarning("操作提示", "当前项目无任务数据，无法导出", parent=self)
            return
        
        # 获取项目名称（用于文件名）
        main_window = self.parent.master.master  # 层级：gantt_panel -> right_vertical_pane -> horizontal_pane -> main
        project_id = main_window.current_project_id if hasattr(main_window, "current_project_id") else None
        project_name = "未命名项目"
        if project_id:
            from data_manager.db_handler import get_project_by_id
            project = get_project_by_id(int(project_id))
            if project:
                project_name = project[1]
        
        # 导出 PDF（Windows 文件名适配）
        filename = f"甘特图_{project_name}_{datetime.now().strftime('%Y%m%d')}.pdf"
        export_figure_to_pdf(self.fig, filename)
